/*
 * Real.h
 * Represents a real value with a precision of t < 52 digits.
 *
 */
#ifndef _REAL_H_
#define _REAL_H_

#include <cmath>
#include <string>

class Real {

public:
	Real();
	Real(const Real &aReal);
	Real(const double &aDouble);

	~Real();

	inline Real &operator+=(const Real &aReal)
	{
		this->_value = (*this + aReal).value();

		return *this;
	}

	inline Real operator+(const Real &aReal) const
	{
		return Real(this->value() + aReal.value());
	}

	inline Real operator-(const Real &aReal) const
	{
		return Real(this->value() - aReal.value());
	}

	inline Real operator*(const Real &aReal) const
	{
		return Real(this->value() * aReal.value());
	}

	inline Real operator/(const Real &aReal) const
	{
		return Real(this->value() / aReal.value());
	}

	inline bool operator==(const Real &aReal) const
	{
		return this->value() == aReal.value();
	}

	inline bool operator<(const Real &aReal) const
	{
		return this->value() < aReal.value();
	}

	inline bool operator>(const Real &aReal) const
	{
		return aReal < *this;
	}

	inline bool operator<=(const Real &aReal) const
	{
		return !(*this > aReal);
	}

	inline bool operator>=(const Real &aReal) const
	{
		return aReal < *this;
	}

	inline Real sqrt() const
	{
		return Real(std::sqrt(this->value()));
	}

	inline double value() const {
		return this->_value;
	}

	std::string to_binary() const;

	static unsigned int precision();
	static void precision(unsigned int digits);

private:
	double _value;

	static bool rounding;
	static unsigned int digits;

	static const unsigned int MAX_DIGITS;

	static double round(double aDouble);
	static double truncate(double aDouble);

	static inline double round_or_truncate(double aDouble) {
		return Real::rounding ?
			Real::round(aDouble) :
			Real::truncate(aDouble);
	}
};

Real operator*(const double &aDouble, const Real &aReal);
Real operator/(const double &aDouble, const Real &aReal);

std::ostream &operator<<(std::ostream &out, const Real &aReal);

#endif /* _REAL_H_ */

